#!/usr/bin/python3.2
# coding: utf-8
from __future__ import division, print_function, unicode_literals
import pygame
import json
from engine import *
from data import *
import tile_rpg

def mix(a,b,c):return [c(a[i],b[i]) for i in range(0,len(a))]
def max(a,b):return a if a>b else b
def min(a,b):return a if a<b else b
def or_none_key(a,k):
	if k in a.keys():return a[k]
	return None

def surf_slice(s,r):
	ret=pygame.Surface(r[2:])
	ret.blit(s,[0]*2,r)
	return ret

class RosterView(Task):
	padding=5
	seperation=10
	c=pygame.time.Clock()
	input_fr=100
	animate_fr=100
	animation_duration=750
	def __init__(self,game,trainer_card):
		Task.__init__(self,game)
		self.stats={}
		for status in ['normal','none','paralyzed','poison','burn']:
			self.stats[status]=sidechain(transparent,game.graphics[key_from_path('ball_stats',status)].copy())
		self.card=trainer_card
		self.party=[trainer_card['storage'][id] for id in trainer_card['roster']]
		self.bg=game.pictures['rosterviewbg'].copy()
		self.cursor_gfx=game.pictures['ball_cursor']
		l=[p for p in self.party]+[None]*(6-len(self.party))
		self.items=[self.make_item(pkmn) for pkmn in l]
		self.threads=[self.paint_bg,self.move,self.paint_items]
		self.cursor=0
		self.time_elapsed=0
		self.item_opacity=0
		self.alpha_step=int(self.animate_fr/self.animation_duration*255)

	def paint_bg(self):
		ball_position=[20,270]
		self.game.surf.blit(self.bg,(0,0))
		pk_list=[pk for pk in self.party]+([None]*(6-len(self.party)))
		status_list=[(or_none_key(pkmn,'status') or 'normal') if pkmn else 'none' for pkmn in pk_list]
		for i,status in enumerate(status_list):
			if i==self.cursor:
				self.game.surf.blit(self.cursor_gfx,mix(ball_position,(12,12),lambda a,b:a-b))
			self.game.surf.blit(self.stats[status],ball_position)
			ball_position[0]+=48

	def paint_items(self):
		default=[20,20]
		position=default[:]
		surf_list=[item['inactive'] for item in self.items[:self.cursor]]
		surf_list=surf_list+[self.items[self.cursor]['active']]
		surf_list=surf_list+[item['inactive'] for item in self.items[self.cursor+1:]]
		h_limit=default[1]
		h_limit+=3*(surf_list[0].get_height()+self.padding)
		for surf in surf_list:
			self.game.surf.blit(surf,position)
			position[1]+=surf.get_height()+self.padding
			if position[1]+surf.get_height() > h_limit:
				position[1]=default[1]
				position[0]+=self.seperation+surf.get_width()

	def move(self):
		upper_bound=len(self.party)
		self.time_elapsed+=self.c.tick()
		if self.time_elapsed>=self.input_fr:
			for k,v in {pygame.K_UP:-1,pygame.K_DOWN:1}.items():
				if self.game.pressed[k]:
					self.cursor+=v
					while self.cursor>=upper_bound:self.cursor-=upper_bound
					while self.cursor<0:self.cursor+=upper_bound
					self.time_elapsed=0
		if pygame.K_RETURN in self.game.just_pressed:
			self.threads=[self.paint_bg,self.scroll,self.paint_summary]
		elif pygame.K_BACKSPACE in self.game.just_pressed:
			self.terminate()

	def scroll(self):
		upper_bound=len(self.party)
		self.time_elapsed+=self.c.tick()
		if self.time_elapsed>=self.input_fr:
			for k,v in {pygame.K_LEFT:-1,pygame.K_RIGHT:1}.items():
				if self.game.pressed[k]:
					self.cursor+=v
					while self.cursor>=upper_bound:self.cursor-=upper_bound
					while self.cursor<0:self.cursor+=upper_bound
					self.time_elapsed=0
		if pygame.K_BACKSPACE in self.game.just_pressed:
			self.threads=[self.paint_bg,self.move,self.paint_items]

	def paint_summary(self):
		sprite_dimensions=[96,96]
		padding=[2,4]
		pos=[20,40]
		col=(255,0,0)
		r=pos+mix(mix(padding,[2,2],lambda a,b:a*b),sprite_dimensions,lambda a,b:a+b)
		self.game.surf.fill(col,r)
		r=mix(pos,padding,lambda a,b:a+b)
		pos=[96,0]+sprite_dimensions
		self.game.surf.blit(self.game.sprites[key_from_path('pokemon',self.party[self.cursor]['species'])],r,pos)

	def make_item(self,data):
		r={}
		r['active']=self.game.pictures['rosterviewhl'].copy()
		r['inactive']=self.game.pictures['rosterviewpk'].copy()
		if data:
			ICON_POS=(5,10)
			TEXT_POS=(40,5)
			r['icon']=self.game.sprites[key_from_path('pokemon','icons',data['species'])].copy()
			r['sprite']=sidechain(transparent,self.game.sprites[key_from_path('pokemon',data['species'])].copy())
			language='English'
			text=data['name'] or self.game.pkdx[data['species']]['name'][language]
			w=r['inactive'].get_width()-TEXT_POS[0]
			w-=w%16
			r['text']=self.game.fonts[self.game.font_table['main']].render(w,text)
			r['active'].blit(r['icon'],ICON_POS)
			r['inactive'].blit(r['icon'],ICON_POS)
			r['active'].blit(r['text'],TEXT_POS)
			r['inactive'].blit(r['text'],TEXT_POS)
		for surf in [r[k] for k in ['active','inactive']]:transparent(surf)
		return r

class PokedexView(Task):

	def __init__(self,game,card):
		Task.__init__(self,game)
		self.species,self.card=[],card
		pkdx=card['pokedex']
		l=[k for k in card['pokedex'].keys()]
		for id,species in game.pkdx.items():
			self.species.append({'type':pkdx[id]if id in l else -1,'id':id,'info':species})
		self.threads=[self.once]

	def once(self):
		for species in self.species:
			if species['type']==-1:print("???")
			elif species['type']==0:print("Seen:",species['info']['name'][self.card['language']])
			elif species['type']==1:print("Caught:",species['info']['name'][self.card['language']])
		self.terminate()

class OverworldMenu(Task):

	width=195
	border_width=5
	bg_color=(40,50,100,180)
	border_color=(240,245,255)
	icon_size=[32,32]
	icon_rotate_r=(-30.0,30.0)
	icon_rotate_i=0.0
	rot_dir=2.0
	ir_rate=10
	ir_elapse=0
	irt=pygame.time.Clock()
	item_padding=16
	adjust_cursor=(32,0)
	items=[
				'pkdx',
				'roster',
				'bag',
				'card',
				'settings',
				'cancel'
			]
	key_mappings={
		pygame.K_UP:-1,
		pygame.K_DOWN:1
	}
	ct=pygame.time.Clock()
	cfr=150
	ct_elapse=0

	def __init__(self,game,save):
		Task.__init__(self,game)
		height=game.surf.get_height()
		self.save=save
		self.open=False
		self.icon_rotated=self.icon_rotate_i
		self.cursor=0
		item_values={
			'pkdx':'Pokedex',
			'roster':'Roster',
			'bag':'Bag',
			'card':save['card']['name'],
			'settings':'Options',
			'cancel':'Cancel'
		}
		for i in range(0,len(self.items)):
			text=self.items[i][:]
			self.items[i]={
				'text':text,
				'surf':game.fonts[game.font_table['menu']].render(self.width-(self.width%16),item_values[text])
			}
		self.bg=pygame.Surface((self.width+self.border_width,height),flags=pygame.SRCALPHA)
		self.bg.fill(self.bg_color,(self.border_width,0,self.width,height))
		pygame.draw.rect(self.bg,self.border_color,(0,0,self.border_width,height))
		self.pos=(game.surf.get_width()-self.width-self.border_width,0)
		self.threads=[self.paint_bg,self.paint_items,self.close_ctl,self.cur_ctl,self.sel_ctl]
		aicon_src=[self.icon_size[0],0]
		iicon_src=[0,0]
		if self.save['card']['gender']=='f':
			aicon_src[0]+=self.icon_size[0]
			iicon_src[0]+=self.icon_size[0]
		self.aicon_src,self.iicon_src=aicon_src,iicon_src

	def paint_bg(self):self.game.surf.blit(self.bg,self.pos,None,pygame.BLEND_RGBA_ADD)

	def hide_menu(self):
		self.open=False
		self.threads=[self.paint_bg,self.paint_items,self.close_ctl,self.cur_ctl,self.sel_ctl]

	def close_ctl(self):
		if pygame.K_BACKSPACE in self.game.just_pressed:self.hide_menu()

	def cur_ctl(self):
		self.ct_elapse+=self.ct.tick()
		upper_bound=len(self.items)
		if self.ct_elapse>=self.cfr:
			for k,v in self.key_mappings.items():
				if self.game.pressed[k]:
					self.cursor+=v
					while self.cursor>=upper_bound:self.cursor-=upper_bound
					while self.cursor<0:self.cursor+=upper_bound
					self.ct_elapse=0
					self.icon_rotated=self.icon_rotate_i

	def paint_items(self):
		pos=[self.game.surf.get_width()-self.width+self.border_width,0]
		self.ir_elapse+=self.irt.tick()
		if self.ir_elapse>=self.ir_rate:
			self.ir_elapse=0
			self.icon_rotated+=self.rot_dir
			if self.icon_rotated>=self.icon_rotate_r[1] or self.icon_rotated<=self.icon_rotate_r[0]:self.rot_dir*=-1

		for surf,text in [(a['surf'],a['text']) for a in self.items]:
			active=surf is self.items[self.cursor]['surf']
			i_src=(self.aicon_src if active else self.iicon_src)+self.icon_size
			icon=surf_slice(self.game.sprites[key_from_path('menu',text)],i_src)
			transparent(icon)
			if active:icon=pygame.transform.rotate(icon,self.icon_rotated)
			transparent(icon)
			pos[1]+=self.item_padding
			sh,ih=surf.get_height(),self.icon_size[1]
			h=max(sh,ih)
			if ih>=sh:
				t_pos=mix(pos,(icon.get_width(),int((ih-sh)/2)),lambda a,b:a+b)
				self.game.surf.blit(icon,pos)
				self.game.surf.blit(surf,t_pos)
			else:
				t_pos=mix(pos,(icon.get_width(),0),lambda a,b:a+b)
				i_pos=mix(pos,(0,0),lambda a,b:a+b)
				self.game.surf.blit(icon,pos)
				self.game.surf.blit(surf,t_pos)
			pos[1]+=h

	def sel_ctl(self):
		if pygame.K_RETURN in self.game.just_pressed:
			v=self.items[self.cursor]['text'].lower()
			if v=='cancel':
				self.hide_menu()
			elif v=='roster':
				self.game.register_task(Callback(self,RosterView(self.game,self.save['card'])))
			elif v=='pkdx':
				self.game.register_task(Callback(self,PokedexView(self.game,self.save['card'])))

class Overworld(Task):

	def __init__(self,game,save):
		Task.__init__(self,game)
		self.threads=[self.paint_bg,self.open_menu]
		self.player_data=save
		self.menu=OverworldMenu(game,save)

	def open_menu(self):
		if self.menu.open:self.menu()
		else: self.menu.open=pygame.K_RETURN in self.game.just_pressed

	def paint_bg(self):self.game.surf.fill([self.frame%256]*3)

class Intro(Task):
	def __init__(self, game):
		Task.__init__(self, game)
		self.bg = game.pictures["titlescreen"]
		self.b_bg = self.bg.convert_alpha()
		self.f_bg = self.bg.convert_alpha()
		self.threads = [self.paint, self.check_keys]
		self.menu = tile_rpg.Menu(game, 80, [(save['card']['name'],save) for save in game.saves.values()]+[("Cancel",None)])

	def paint(self):self.game.surf.blit(self.bg, (0, 0))

	def check_keys(self):
		if pygame.K_RETURN in self.game.just_pressed:
			self.menu.reset()
			self.threads = [ self.paint, self.menu, self.load_games]
		self.game.just_pressed = []

	def load_games(self):
		if not self.menu.open:
			if self.menu.value is not None:
				ow=Overworld(self.game, self.menu.value)
				self.game.register_task(FadeOut(self.game,25,ow,5,(255,255,255)))
				self.terminate()
			else:
				self.menu.open = False
				self.threads = [ self.paint, self.check_keys]

class PyPokemon(Game):
	maps = Cache("maps", json.load)
	tilesets = Cache("tilesets",load_trans_image,['r+b'])
	sprites = Cache("sprites", load_trans_image,['r+b'])
	pkdx = load_data('species', json.load)
	saves = load_data('saves', json.load)
	info = load_data("info", json.load)
	graphics = Cache("graphics",load_trans_image,['r+b'])
	pictures = Cache("images", pygame.image.load,['r+b'])
	fonts = load_data("fonts", load_font,'r+b')
	tileset_data = Cache("tilesets data",json.load)
	npc_types=Cache("trainers")
	res,center=(480,320),(480/16/2,320/16/2)
	def __init__(self):
		Game.__init__(self, self.res)
		self.font_table = { 'main':'rainhearts', 'menu':'fontwestern'}
		self.register_task(Intro(self))

if __name__ == "__main__": run(PyPokemon())
